package logica.users;

import java.util.ArrayList;
import java.util.List;

import logica.email.EmailIF;
import logica.email.FacadeEmail;
import logica.exceptions.InvalidDataException;
import logica.exceptions.RequiredDataException;
import logica.exceptions.UserDoesNotContainProductsException;
import logica.interfaces.AuctionListener;
import logica.interfaces.UserIF;
import logica.product.AuctionAnnouncementEvent;

/**
 * Classe que implementa um usuario de um leilao vitual.
 *
 */
public class User implements UserIF, AuctionListener {

	// login de acesso ao sistema do usuario
	private String login;

	// nome do usuario
	private String name;

	// email do usuario
	private String email;

	// senha de acesso que precisa ser combinada com o login
	private String password;

	// endereco do usuario
	private String address;

	// cpf do usuario
	private String cpfNumber;

	// Telefone do Usuario
	private String phoneNumber;

	// Status de usuario vendedor
	private int status;

	// Lista de itens leiloaveis pertencente ao cliente
	private List<String> productList;

	/**
	 * Construtor de um usuario e um sistema de leilao virtual.
	 *
	 * @param login
	 *            login de acesso ao sistema do usuario.
	 * @param name
	 *            nome do usuario.
	 * @param email
	 *            email do usuario.
	 * @param password
	 *            senha de acesso que precisa ser combinada com o login.
	 * @param address
	 *            endereco do usuario.
	 * @param cpfNumber
	 *            cpf do usuario.
	 * @param phoneNumber
	 *            numero de telefone do Usuario.
	 * @throws InvalidDataException
	 *             Se algum dado fornecido for invalido.
	 * @throws RequiredDataException
	 *             Se algum dado nao for fornecido.
	 */
	public User(String login, String name, String email, String password,
			String address, String cpfNumber, String phoneNumber)
			throws InvalidDataException, RequiredDataException {
		this.setLogin(login);
		this.setName(name);
		this.setEmail(email);
		this.setPassword(password);
		this.setAddress(address);
		this.setCpfNumber(cpfNumber);
		this.setPhoneNumber(phoneNumber);
		this.addStatus(0);
		this.productList = new ArrayList<String>();
	}

	/**
	 * Adiciona um status ao usuario.
	 *
	 * @param O
	 *            status adicionado.
	 * @throws RequiredDataException
	 *             Se o status for nulo ou vazio.
	 */
	public void addStatus(int status) throws RequiredDataException {
		this.status = status;
	}

	/**
	 * Retorna o endereco do usuario.
	 *
	 * @return o endereco do usuario.
	 */
	public String getAddress() {
		return this.address;
	}

	/**
	 * Retorna o endereco do usuario.
	 *
	 * @return o endereco do usuario.
	 */
	public String getCpfNumber() {
		return this.cpfNumber;
	}

	/**
	 * Retorna o endereco de email do usuario.
	 *
	 * @return o endereco de email do usuario.
	 */
	public String getEmail() {
		return this.email;
	}

	/**
	 * Retorna o login do usuario.
	 *
	 * @return o login do usuario.
	 */
	public String getLogin() {
		return this.login;
	}

	/**
	 * Retorna o nome do usuario.
	 *
	 * @return o nome do usuario.
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * Retorna a senha do usuario.
	 *
	 * @return a senha do usuario.
	 */
	public String getPassword() {
		return this.password;
	}

	/**
	 * Retorna o numero de telefone do usuario.
	 *
	 * @return o numero de telefone do usuario.
	 */
	public String getPhoneNumber() {
		return this.phoneNumber;
	}

	/**
	 * Retorna o status do usuario.
	 *
	 * @return o status do usuario.
	 */
	public int getStatus() {
		return this.status;
	}

	/**
	 * Retorna o produto de indice index da lista de produtos do usuario.
	 *
	 * @param index
	 *            o indice da lista de produtos do usuario.
	 * @return o produto de indice index da lista de produtos do usuario.
	 */
	public String listProduct(int index) {
		return this.productList.get(index);
	}

	/**
	 * Atualiza o endereco do usuario.
	 *
	 * @param address
	 *            O novo endereco.
	 * @throws RequiredDataException
	 *             Se o parametro for nulo ou vazio.
	 */
	public void setAddress(String address) throws RequiredDataException {
		if ((address == null) || (address.equals("")))
			throw new RequiredDataException("address");

		this.address = address;
	}

	/**
	 * Atualiza o numero de cpf do usuario.
	 *
	 * @param address
	 *            O novo numero de cpf.
	 * @throws InvalidDataException
	 *             Se o parametro nao for um numero de cpf.
	 * @throws RequiredDataException
	 *             Se o parametro for nulo ou vazio.
	 *
	 */
	public void setCpfNumber(String cpfNumber) throws InvalidDataException,
			RequiredDataException {
		if ((cpfNumber == null) || (cpfNumber.equals("")))
			throw new RequiredDataException("CPF number");

		if (!this.isCpf(cpfNumber))
			throw new InvalidDataException("CPF number");

		this.cpfNumber = cpfNumber;
	}

	/**
	 * Atualiza o endereco de email do usuario.
	 *
	 * @param address
	 *            O novo endereco de email.
	 * @throws InvalidDataException
	 *             Se o parametro nao for um endereco de email.
	 * @throws RequiredDataException
	 *             Se o parametro for nulo ou vazio.
	 *
	 */
	public void setEmail(String email) throws InvalidDataException,
			RequiredDataException {
		if ((email == null) || (email.equals("")))
			throw new RequiredDataException("email");

		if (!this.isEmail(email))
			throw new InvalidDataException("email");

		this.email = email;

	}

	/**
	 * Atualiza o login do usuario.
	 *
	 * @param address
	 *            O novo login.
	 * @throws RequiredDataException
	 *             Se o parametro for nulo ou vazio.
	 */
	public void setLogin(String login) throws RequiredDataException {
		if ((login == null) || (login.equals("")))
			throw new RequiredDataException("login");

		this.login = login;

	}

	/**
	 * Atualiza o nome do usuario.
	 *
	 * @param address
	 *            O novo nome.
	 * @throws RequiredDataException
	 *             Se o parametro for nulo ou vazio.
	 */
	public void setName(String name) throws RequiredDataException {
		if ((name == null) || (name.equals("")))
			throw new RequiredDataException("name");

		this.name = name;

	}

	/**
	 * Atualiza a senha do usuario.
	 *
	 * @param address
	 *            A nova senha.
	 * @throws RequiredDataException
	 *             Se o parametro for nulo ou vazio.
	 */
	public void setPassword(String password) throws RequiredDataException {
		if ((password == null) || (password.equals("")))
			throw new RequiredDataException("password");

		this.password = password;
	}

	/**
	 * Atualiza o numero de telefone do usuario.
	 *
	 * @param address
	 *            O novo numero de telefone.
	 * @throws RequiredDataException
	 *             Se o parametro for nulo ou vazio.
	 */
	public void setPhoneNumber(String tel) throws RequiredDataException {
		if ((tel == null) || (tel.equals("")))
			throw new RequiredDataException("phone number");

		this.phoneNumber = tel;

	}

	/*
	 * Analisa se um dado cpf e valido. Analisa a quantidade de digitos do cpf.
	 */
	private boolean isCpf(String cpfNumber) {
		if (cpfNumber.length() == 12) {
			return true;
		} else {
			return false;
		}
	}

	/*
	 * Analisa se o string do email contem o simbolo @. Isto indica um email
	 * valido.
	 */
	private boolean isEmail(String email) {
		return email.contains("@");
	}

	/**
	 * Usuarios sao igualados por login.
	 *
	 * @param obj
	 *            O objeto a ser comparado.
	 * @return True se os objetos tiverem o mesmo login.
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj instanceof User) {
			User user = (User) obj;
			return this.login.equals(user.getLogin());
		}
		return false;
	}

	/**
	 * Remove todos os produtos de um usuario.
	 *
	 * @throws UserDoesNotContainProductsException
	 *             Se um usuario nao tiver produtos.
	 */
	public void removeAllProducts() throws UserDoesNotContainProductsException {
		if (productList.isEmpty())
			throw new UserDoesNotContainProductsException();
		productList.clear();
	}

	/**
	 * Remove um produto do um usuario.
	 *
	 * @param String
	 *            productId
	 * @throws UserDoesNotContainProductsException
	 *             Se o usuario nao tiver o produto.
	 */
	public void removeProducts(String productId)
			throws UserDoesNotContainProductsException {
		if (productList == null)
			if (!productList.contains(productId))
				throw new UserDoesNotContainProductsException();
		productList.remove(productId);

	}

	/**
	 * Adiciona um produto a lista de produtos do usuario.
	 *
	 * @param productId
	 *            O id do produto adicionado.
	 */
	public void addProduct(String productId) {
		this.productList.add(productId);

	}

	/**
	 * Retorna todos os produtos do usuario.
	 *
	 * @return Todos os produtos do usuario.
	 */
	public List<String> getAllProducts() {
		return this.productList;
	}

	/**
	 * Aumenta o status do usuario.
	 */
	public void setStatusUp() {
		this.status = this.status + 1;
	}

	/**
	 * Diminui o status do usuario.
	 */
	public void setStatusDown() {
		this.status = this.status + 1;
	}

	/**
	 * Recepcao de um anuncio de um leilao de um produto que este usuario se
	 * interessou.
	 *
	 * @param a
	 *            O anuncio do inicio de um leilao.
	 */
	public void receiveEvent(AuctionAnnouncementEvent a) {
		EmailIF email = new FacadeEmail();
		String subject = "Inicio do leilao do produto "
				+ a.getProductDescription();
		String text = "Anunciamos o inicio do leilao descrito por "
				+ a.getAuctionDescription() + "\n" + "com data marcada para"
				+ a.getDate() + " das " + a.getBeginTime() + " as "
				+ a.getEndTime() + "." + "\n" + "Este leilao pertece a "
				+ a.getAuctionDescription() + "." + "\n"
				+ "O produto em leilao eh " + a.getProductDescription()
				+ " cujo lance minimo eh " + a.getMinimalBid() + ".";
		email.send(this.email, subject, text);

	}

	/**
	 * Notifica um usuario que ele venceu o leilao.
	 *
	 * @param auctionName
	 *            Nome do leilao.
	 * @param product
	 *            nome do produto.
	 */
	public void notifyWinnerAuction(String auctionName, String auctionProduct) {
		EmailIF email = new FacadeEmail();
		String subject = "Parabens voce venceu um leilao";
		String text = "Caro " + this.name + ", Voce venceu o leilao chamado: "
				+ auctionName + "\n" + " do produto " + auctionProduct
				+ ". Entre em contato com o organizador." + "\n" + "Obrigado!";
		email.send(this.getEmail(), subject, text);
	}
}